/**
 * <b>Map class:</b>
 * <hr color=grey size=1>
 * 
 *An object that maps keys to values. A map cannot contain duplicate keys;
 *each key can map to one value. 
 *
 * <br>
 *  
 * @author th  created @ 2006
 *
 */

ihelpuoo.util.map = function()
{
	return new ihelpuoo.util.Map();
}

ihelpuoo.util.Map = function()
{
	this.data = new Object();
	this._size = 0;
}

ihelpuoo.util.Map.prototype
=
{
	/**
	 * Removes all mappings from this map 
	 * 
	 */
	clear : function()
	{
		delete this.data;
		//replace old object, let it recycle by the GC.
		//for(var inKey in this.data)
		//{
		//	delete this.data[inKey];
		//}
		this.data = new Object();
		this._size = 0;
	},
	
	/**
	 * @param key whose associated value is to be returned.
	 * @return true if this map contains
	 * a mapping for the specified key.
	 */
	containsKey : function(key)
	{
		return (this.data[key]!=undefined);
	},
	
	/**
	 * @param value whose presence in this map is to be tested.
	 * @return true if this map contains
	 * a mapping for the specified value.
	 */
	containsValue : function(val)
	{
		for(var inKey in this.data)
		{
			if(this.data[inKey]!= undefined && this.data[inKey] == val)
			{
				return true;
			}
		}
		return false;		
	},
	
	/**
	 * @param key whose associated value is to be returned.
	 * @return the value to which this map maps the specified key.
	 */
	get : function(key)
	{
		if(this.data[key]==undefined)
		{
			return null;
		}
		return this.data[key];
	},
	
	/**
	 * @return true if this map contains no key-value mappings.
	 */
	isEmpty : function()
	{
		return this._size<=0;
	},
	
	/**
	 * Associates the specified value with the specified key in this map (optional operation). 
	 * If the map previously contained a mapping for this key, 
	 * the old value is replaced by the specified value. 
	 * (A map m is said to contain a mapping for a key k if and 
	 * only if m.containsKey(k) would return true.)) 

	 * @param key whose associated value is to be returned.
	 * @param value whose presence in this map is to be tested.
	 * 
	 * @return previous value associated with specified key, 
	 * or null if there was no mapping for key. 
	 */
	put : function(key,val)
	{
		var retVal = null;
		if(this.data[key]!=undefined)
		{
			retVal = this.data[key];
			this._size--;
		}
		this.data[key] = val;
		this._size ++;
		return retVal;
	},
	
	/**
	 * Removes the mapping for this key from this map 
	 * if it is present (optional operation). 
	 * More formally, if this map contains a mapping 
	 * from key k to value v such that 
	 * (key==null ? k==null : key.equals(k)), 
	 * that mapping is removed. 
	 * (The map can contain at most one such mapping.)  
	 *
	 * @param key whose associated value is to be returned.
	 * 
	 * @return previous value associated with specified key, 
	 * or null if there was no mapping for key. 
	 */
	remove : function(key)
	{
		if(this.data[key]==undefined)return;
		var retVal = this.data[key];
		delete this.data[key];
		this._size--;
		return retVal;
	},
	
	/**
	 * @return the number of key-value mappings in this map.
	 */
	size : function()
	{
		return this._size;
	},

	/**
	 * @return an array of the keys contained in this map.
	 */
	keys : function()
	{
		var keyArray = new Array();
		for(var inKey in this.data)
		{
			keyArray.push(inKey);
		}
		return keyArray;
	},

	/**
	 * @return an array of the values contained in this map.
	 */
	values : function()
	{
		var valArray = new Array();
		for(var inKey in this.data)
		{
			valArray.push(this.data[inKey]);
		}
		return valArray;
	}
}
